Plotting in Julia

Biostat/Biomath M257

Author

Dr. Hua Zhou @ UCLA

Published

April 4, 2024

System information (for reproducibility):

versioninfo()
Julia Version 1.10.2
Commit bd47eca2c8a (2024-03-01 10:14 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: macOS (arm64-apple-darwin22.4.0)
  CPU: 12 × Apple M2 Max
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, apple-m1)
Threads: 8 default, 0 interactive, 4 GC (on 8 virtual cores)
Environment:
  JULIA_NUM_THREADS = 8
  JULIA_EDITOR = code
  DYLD_FALLBACK_LIBRARY_PATH = /Users/huazhou/.julia/artifacts/5902919ba30b97bafa388ca950a351ea32516d26/lib:/Users/huazhou/.julia/artifacts/92b949e2f3a66439c69a8d334fc95810fbd9df9b/lib:/Users/huazhou/.julia/artifacts/5b338c8fa90c05e6faea86e54d2996cca76cfbbe/lib:/Users/huazhou/.julia/juliaup/julia-1.10.2+0.aarch64.apple.darwin14/lib/julia:/Users/huazhou/.julia/artifacts/0b234a64c0574e6156c740b15844963c0555164e/lib:/Users/huazhou/.julia/artifacts/9410bad2635eda2239b4a72ba4316c4aa8f5b76e/lib:/Users/huazhou/.julia/artifacts/a7cf2895cac9b6bec2c94e6490ca337e00b12894/lib:/Users/huazhou/.julia/artifacts/10b2b258c07d7a76b2e3331f1ed70d8a8eb6d71c/lib:/Users/huazhou/.julia/artifacts/9a76a401f82e0e3cafce618fb8d2d5c307ab2836/lib:/Users/huazhou/.julia/artifacts/e8b17d4e8df51de281bf55f890ba48f924e41ce3/lib:/Users/huazhou/.julia/artifacts/c65e07e3da4f1bf519bc432389dbbd61df320457/lib:/Users/huazhou/.julia/artifacts/4ec62d729213a748d2300dd0832ebe8ed2292093/lib:/Users/huazhou/.julia/artifacts/e6b9fb44029423f5cd69e0cbbff25abcc4b32a8f/lib:/Users/huazhou/.julia/artifacts/fb8b9a86c16889fbeb669622623a954bb773fce8/lib:/Users/huazhou/.julia/artifacts/df3881e810714d6a09467fe85a6fde79385fe702/lib:/Users/huazhou/.julia/artifacts/3b3d0bcaf14a9b239a4f4dc20ef7b9e63030a47e/lib:/Users/huazhou/.julia/artifacts/abf161ac3d4df76ae74bbf5432b7e061b3876236/lib:/Users/huazhou/.julia/artifacts/4260cf51a368d8e305a5de3669e32539e1e6cc72/lib:/Users/huazhou/.julia/artifacts/fc7ba632b72ce7d852c1924aa2bbfe244a71c780/lib:/Users/huazhou/.julia/artifacts/413111420faa4e2aeaa383c075eaa213402d939c/lib:/Users/huazhou/.julia/artifacts/ca2831bf6edc5088aec5b329ea98364951d6cad0/lib:/Users/huazhou/.julia/artifacts/3fe6bf926e57cc4be598151cd40832221de2e894/lib:/Users/huazhou/.julia/artifacts/c325a23bc1f6521474cef5f634f18c8ab311bb02/lib:/Users/huazhou/.julia/artifacts/0db9c3f6cf936a0da49e2ba954ba3e10bed6ad72/lib:/Users/huazhou/.julia/artifacts/1a7e22e66b523d9cb884cf85c3ec065b5fb3e5c3/lib:/Users/huazhou/.julia/artifacts/91d16d8e67cf04eb9240c5d28f057b567e2b8dab/lib:/Users/huazhou/.julia/artifacts/4609432e7098d8434a7a4c7876dd5b9e09b2a5e7/lib:/Users/huazhou/.julia/artifacts/6095fcd268ea712c0f786f5ff1a45bf0eb7b005e/lib:/Users/huazhou/.julia/artifacts/8dfccc7f1aa9d156f12a6e7db599014b805b11f2/lib:/Users/huazhou/.julia/artifacts/13ab26d7214d6ea78e7839477d2262c18b38b450/lib:/Users/huazhou/.julia/artifacts/b450526929615030746974fd622effa333c2c87a/lib:/Users/huazhou/.julia/artifacts/fb653fdc268e50c0be4391f6ca2f2fce2be7f15b/lib:/Users/huazhou/.julia/artifacts/3908ba61f3e144a7e7e28b9d676ca770f2f6a955/lib:/Users/huazhou/.julia/artifacts/2107e7bc404f11b178cb9724cb371ef704995727/lib:/Users/huazhou/.julia/artifacts/4b3b2d79556cc3aef6e3d8a234649cc85b91bb87/lib:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtConcurrent.framework/Versions/A:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtCore.framework/Versions/A:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtDBus.framework/Versions/A:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtGui.framework/Versions/A:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtNetwork.framework/Versions/A:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtOpenGL.framework/Versions/A:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtPrintSupport.framework/Versions/A:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtSql.framework/Versions/A:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtTest.framework/Versions/A:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtWidgets.framework/Versions/A:/Users/huazhou/.julia/artifacts/dc1fe71ef939802ae7490350407bea0f47e5be5f/lib/QtXml.framework/Versions/A:/Users/huazhou/.julia/artifacts/2711a7295dd2796d38718436686a5cdfe32d1d1c/lib:/Users/huazhou/.julia/juliaup/julia-1.10.2+0.aarch64.apple.darwin14/bin/../lib/julia:/Users/huazhou/.julia/juliaup/julia-1.10.2+0.aarch64.apple.darwin14/bin/../lib:

Load packages:

using Pkg
Pkg.activate(pwd())
Pkg.instantiate()
Pkg.status()
  Activating project at `~/Documents/github.com/ucla-biostat-257/2024spring/slides/04-juliaplot`
Status `~/Documents/github.com/ucla-biostat-257/2024spring/slides/04-juliaplot/Project.toml`
  [c91e804a] Gadfly v1.4.0
  [f0f68f2c] PlotlyJS v0.18.13
  [91a5bcdd] Plots v1.40.3
  [d330b81b] PyPlot v2.11.2
  [6f49c342] RCall v0.14.1
  [9a3f8284] Random
using Gadfly, Plots, PlotlyJS, PyPlot, Random, RCall

1 Plotting in Julia

The popular options (currently) for plotting in Julia are:

1.1 Gadfly.jl

To demonstrate Gadfly, we will go through an example and compare it to ggplot2.

using RCall

R"""
library(ggplot2)
library(dplyr)

df <- ToothGrowth %>%
  group_by(supp, dose) %>%
  summarise(se = sd(len) / n(), len = mean(len), n = n())

ggplot(df, aes(x = dose, y = len, group = supp, color = supp)) + 
  geom_line() +
  geom_point() +
  geom_errorbar(aes(ymin = len - se, ymax = len + se), width = 0.1, alpha = 0.5,
  position = position_dodge(0.005)) +  
  scale_color_manual(values = c(VC = "skyblue", OJ = "orange")) + 
  labs(x = "Dose", y = "Tooth Length")
"""
┌ Warning: RCall.jl: `summarise()` has grouped output by 'supp'. You can override using the
│ `.groups` argument.
└ @ RCall /Users/huazhou/.julia/packages/RCall/dDAVd/src/io.jl:172
RObject{VecSxp}
@rget df # retrieve dataframe from R to Julia workspace
using Gadfly
df[!, :ymin] = df[!, :len] - df[!, :se]
df[!, :ymax] = df[!, :len] + df[!, :se]
Gadfly.plot(df, 
    x = :dose, 
    y = :len, 
    color = :supp, 
    Geom.point,
    Guide.xlabel("Dose"), 
    Guide.ylabel("Tooth Length"), 
    Guide.xticks(ticks = [0.5, 1.0, 1.5, 2.0]),
    Geom.line, 
    Geom.errorbar, 
    ymin = :ymin, 
    ymax = :ymax, 
    Scale.color_discrete_manual("orange", "skyblue"))
Dose 0.5 1.0 1.5 2.0 OJ VC supp 2.0,26.14 1.0,16.77 0.57.9799999999999995 2.0,26.06 1.0,22.7 0.5,13.23 h,j,k,l,arrows,drag to pan i,o,+,-,scroll,shift-drag to zoom r,dbl-click to reset c for coordinates ? for help ? 0 10 20 30 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13.0 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14.0 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15.0 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 16.0 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17.0 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18.0 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19.0 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.9 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 25.0 25.1 25.2 25.3 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8 27.9 28.0 28.1 28.2 28.3 28.4 28.5 28.6 28.7 28.8 28.9 29.0 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 30.0 0 30 Tooth Length

Both offer more customized options

R"""
ggplot(df, aes(x = dose, y = len, group = supp, color = supp)) + 
  geom_line() +
  geom_point() +
  geom_errorbar(aes(ymin = len - se, ymax = len + se), width = 0.1, alpha = 0.5, 
    position = position_dodge(0.005)) + 
    theme(legend.position = c(0.8,0.1), 
    legend.key = element_blank(), 
    axis.text.x = element_text(angle = 0, size = 11), 
    axis.ticks = element_blank(), 
    panel.grid.major = element_blank(), 
    legend.text=element_text(size = 11),
    panel.border = element_blank(), 
    panel.grid.minor = element_blank(), 
    panel.background = element_blank(), 
    axis.line = element_line(color = 'black',size = 0.3), 
  plot.title = element_text(hjust = 0.5)) + 
  scale_color_manual(values = c(VC = "skyblue", OJ = "orange")) + 
  labs(x = "Dose", y = "Tooth Length")
"""
RObject{VecSxp}
Gadfly.plot(df, x = :dose, y = :len, color = :supp, Geom.point,
    Guide.xlabel("Dose"), Guide.ylabel("Tooth Length"), 
    Guide.xticks(ticks = [0.5, 1.0, 1.5, 2.0]),
    Theme(panel_fill = nothing, highlight_width = 0mm, point_size = 0.5mm,
    key_position = :inside, 
    grid_line_width = 0mm, panel_stroke = colorant"black"),
    Geom.line, Geom.errorbar, ymin = :ymin, ymax = :ymax, 
    Scale.color_discrete_manual("orange", "skyblue"))
Dose 0.5 1.0 1.5 2.0 2.0,26.14 1.0,16.77 0.57.9799999999999995 2.0,26.06 1.0,22.7 0.5,13.23 OJ VC supp h,j,k,l,arrows,drag to pan i,o,+,-,scroll,shift-drag to zoom r,dbl-click to reset c for coordinates ? for help ? 0 10 20 30 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.0 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 12.1 12.2 12.3 12.4 12.5 12.6 12.7 12.8 12.9 13.0 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8 13.9 14.0 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8 14.9 15.0 15.1 15.2 15.3 15.4 15.5 15.6 15.7 15.8 15.9 16.0 16.1 16.2 16.3 16.4 16.5 16.6 16.7 16.8 16.9 17.0 17.1 17.2 17.3 17.4 17.5 17.6 17.7 17.8 17.9 18.0 18.1 18.2 18.3 18.4 18.5 18.6 18.7 18.8 18.9 19.0 19.1 19.2 19.3 19.4 19.5 19.6 19.7 19.8 19.9 20.0 20.1 20.2 20.3 20.4 20.5 20.6 20.7 20.8 20.9 21.0 21.1 21.2 21.3 21.4 21.5 21.6 21.7 21.8 21.9 22.0 22.1 22.2 22.3 22.4 22.5 22.6 22.7 22.8 22.9 23.0 23.1 23.2 23.3 23.4 23.5 23.6 23.7 23.8 23.9 24.0 24.1 24.2 24.3 24.4 24.5 24.6 24.7 24.8 24.9 25.0 25.1 25.2 25.3 25.4 25.5 25.6 25.7 25.8 25.9 26.0 26.1 26.2 26.3 26.4 26.5 26.6 26.7 26.8 26.9 27.0 27.1 27.2 27.3 27.4 27.5 27.6 27.7 27.8 27.9 28.0 28.1 28.2 28.3 28.4 28.5 28.6 28.7 28.8 28.9 29.0 29.1 29.2 29.3 29.4 29.5 29.6 29.7 29.8 29.9 30.0 0 30 Tooth Length

1.2 Plots.jl

We demonstrate Plots.jl below:

# Pkg.add("Plots")
using Plots, Random

Random.seed!(123) # set seed
x = cumsum(randn(50, 2), dims=1);
# Pkg.add("PyPlot")
pyplot()  # set the backend to PyPlot
Plots.plot(x, title="Random walk", xlab="time")
gr()   # change backend to GR
Plots.plot(x, title="Random walk", xlab="time")
gr()
@gif for i in 1:20
    Plots.plot(x -> sin(x) / (.2i), 0, i, xlim=(0, 20), ylim=(-.75, .75))
    scatter!(x -> cos(x) * .01 * i, 0, i, m=1)
end;

produces following animation.

# Pkg.add("PlotlyJS")
plotlyjs()  # change backend to PlotlyJS
Plots.plot(x, title="Random walk", xlab="time")